package com.xmb.common.service.wx.impl;

import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.xmb.common.constants.PayStatusEnum;
import com.xmb.common.dao.XmbWechatPaymentOrderMapper;
import com.xmb.common.dao.XmbWechatPaymentRefundMapper;
import com.xmb.common.entity.XmbWechatPaymentOrder;
import com.xmb.common.entity.XmbWechatPaymentRefund;
import com.xmb.common.entity.XmbXcxAccountConfig;
import com.xmb.common.exception.BusinessException;
import com.xmb.common.interceptor.CurrentContextUser;
import com.xmb.common.params.WxPayRefundParam;
import com.xmb.common.params.WxPayUnifiedOrdeParam;
import com.xmb.common.service.XcxAccountService;
import com.xmb.common.service.wx.WxCommonService;
import com.xmb.common.service.wx.WxPayRefundService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

/**
 * Created by lyndon on 2019/4/11.
 */
@Service
public class WxPayRefundServiceImpl implements WxPayRefundService {

    public final static String PAYMENT_TYPE = "JSAPI";

    public final static String REFUND_TYPE = "CNY";

    /**
     * 退款的回调接口
     */
    @Value("${wechat.refund.notify}")
    private String refundNotify;

    @Resource
    private XcxAccountService accountService;

    @Resource
    private XmbWechatPaymentOrderMapper wechatPaymentOrderMapper;

    @Resource
    private XmbWechatPaymentRefundMapper wechatPaymentRefundMapper;

    private WxPayService wxPayService;

    @Resource
    private WxCommonService wxCommonService;

    @Override
    @Transactional
    public int applyRefundOrder(WxPayRefundParam refundParam) throws WxPayException {
        // 设置支付配置信息
        XmbXcxAccountConfig xcxAccountConfig = accountService.selectByAppid(CurrentContextUser.get().getAppid());
        if (xcxAccountConfig == null) {
            throw new BusinessException("无法获取当前小程序的支付配置信息");
        }
        XmbWechatPaymentOrder paymentOrder = new XmbWechatPaymentOrder();
        paymentOrder.setWxTransactionNo(refundParam.getWxTransactionNo());
        paymentOrder.setMerchantTransactionNo(refundParam.getMerchantTransactionNo());
        paymentOrder.setPayStatus(PayStatusEnum.paid.name());
        XmbWechatPaymentOrder xmbWechatPaymentOrder
                = wechatPaymentOrderMapper.selectByMerchantTransactionNoAndWxNo(paymentOrder);
        if (xmbWechatPaymentOrder == null) {
            throw new BusinessException("当前订单未支付成功或者不存在");
        }
        if (xmbWechatPaymentOrder.getPaymentAmount().compareTo(refundParam.getRefundAmount()) == -1){
            throw new BusinessException("退款金额不能大于当前订单支付总额");
        }
        // 判断当前订单是否已经发起退款
        XmbWechatPaymentRefund wechatPaymentRefund = new XmbWechatPaymentRefund();
        wechatPaymentRefund.setMerchantTransactionNo(refundParam.getMerchantTransactionNo());
        wechatPaymentRefund.setWxTransactionNo(refundParam.getWxTransactionNo());
        XmbWechatPaymentRefund paymentRefund = wechatPaymentRefundMapper.selectXmbWechatPaymentRefund(wechatPaymentRefund);
        if (paymentRefund !=null) {
            throw new BusinessException("当前订单已经发起过退款申请,不能再次发起申请");
        }
        // 保存数据
        return this.saveApplyRefundInfo(xmbWechatPaymentOrder,refundParam);
    }


    private int saveApplyRefundInfo(XmbWechatPaymentOrder xmbWechatPaymentOrder, WxPayRefundParam refundParam) {
        XmbWechatPaymentRefund wechatPaymentRefund = new XmbWechatPaymentRefund();
        wechatPaymentRefund.setUserId(xmbWechatPaymentOrder.getUserId());
        wechatPaymentRefund.setWxTransactionNo(xmbWechatPaymentOrder.getWxTransactionNo());
        wechatPaymentRefund.setMerchantTransactionNo(xmbWechatPaymentOrder.getMerchantTransactionNo());
        wechatPaymentRefund.setMerchantId(xmbWechatPaymentOrder.getMerchantId());
        wechatPaymentRefund.setRefundAmount(refundParam.getRefundAmount());
        wechatPaymentRefund.setRefundStatus(PayStatusEnum.refunding.name());
        wechatPaymentRefund.setRefundAmount(refundParam.getRefundAmount());
        wechatPaymentRefund.setTotalAmount(xmbWechatPaymentOrder.getPaymentAmount());
        wechatPaymentRefund.setSenceId(xmbWechatPaymentOrder.getSenceId());
        return wechatPaymentRefundMapper.insertSelective(wechatPaymentRefund);
    }



    @Override
    public WxPayRefundResult autoRefundOrder(WxPayUnifiedOrdeParam ordeParam) throws WxPayException {
        XmbWechatPaymentOrder paymentOrder = new XmbWechatPaymentOrder();
        paymentOrder.setSenceId(ordeParam.getOrderId());
        paymentOrder.setSenceType(ordeParam.getOrderType());
        paymentOrder.setPayStatus(PayStatusEnum.paid.name());
        paymentOrder = wechatPaymentOrderMapper.selectBySenceIdAndType(paymentOrder);
        WxPayRefundParam refundParam = new WxPayRefundParam();
        refundParam.setRefundAmount(paymentOrder.getPaymentAmount());
        refundParam.setMerchantTransactionNo(paymentOrder.getMerchantTransactionNo());
        refundParam.setWxTransactionNo(paymentOrder.getWxTransactionNo());
        refundParam.setRefundDesc("取消订单");
        return this.autoRefundOrder(refundParam,paymentOrder.getAppId());
    }

    @Transactional
    public WxPayRefundResult autoRefundOrder(WxPayRefundParam refundParam,String appid) throws WxPayException {
        // 设置支付配置信息
        XmbXcxAccountConfig xcxAccountConfig = accountService.selectByAppid(appid);
        if (xcxAccountConfig == null) {
            throw new BusinessException("无法获取当前小程序的支付配置信息");
        }
        XmbWechatPaymentOrder paymentOrder = new XmbWechatPaymentOrder();
        paymentOrder.setWxTransactionNo(refundParam.getWxTransactionNo());
        paymentOrder.setMerchantTransactionNo(refundParam.getMerchantTransactionNo());
        paymentOrder.setPayStatus(PayStatusEnum.paid.name());
        XmbWechatPaymentOrder xmbWechatPaymentOrder
                = wechatPaymentOrderMapper.selectByMerchantTransactionNoAndWxNo(paymentOrder);
        if (xmbWechatPaymentOrder == null) {
            throw new BusinessException("当前订单未支付成功或者不存在");
        }
        if (xmbWechatPaymentOrder.getPaymentAmount().compareTo(refundParam.getRefundAmount()) == -1){
            throw new BusinessException("退款金额不能大于当前订单支付总额");
        }
        // 判断当前订单是否已经发起退款
        XmbWechatPaymentRefund wechatPaymentRefund = new XmbWechatPaymentRefund();
        wechatPaymentRefund.setMerchantTransactionNo(refundParam.getMerchantTransactionNo());
        wechatPaymentRefund.setWxTransactionNo(refundParam.getWxTransactionNo());
        XmbWechatPaymentRefund paymentRefund = wechatPaymentRefundMapper.selectXmbWechatPaymentRefund(wechatPaymentRefund);
        if (paymentRefund !=null) {
            throw new BusinessException("当前订单已经发起过退款申请,不能再次发起申请");
        }
        this.setWxPayRefundConfig(xcxAccountConfig);
        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
        wxPayRefundRequest.setOutRefundNo(wxCommonService.getRefundOutTranceNo());
        wxPayRefundRequest.setRefundFee(refundParam.getRefundAmount().multiply(new BigDecimal(100)).intValue());
        wxPayRefundRequest.setTotalFee(xmbWechatPaymentOrder.getPaymentAmount().multiply(new BigDecimal(100)).intValue());
        wxPayRefundRequest.setRefundFeeType(REFUND_TYPE);
        wxPayRefundRequest.setOutTradeNo(xmbWechatPaymentOrder.getMerchantTransactionNo());
        wxPayRefundRequest.setTransactionId(xmbWechatPaymentOrder.getWxTransactionNo());
        WxPayRefundResult payRefundResult = wxPayService.refund(wxPayRefundRequest);
        // 保存数据
        this.saveRefundInfo(payRefundResult,xmbWechatPaymentOrder,refundParam);
        return payRefundResult;
    }


    /**
     * 设置退款配置信息
     */
    private void setWxPayRefundConfig(XmbXcxAccountConfig xcxAccountConfig ){
        wxPayService = new WxPayServiceImpl();
        WxPayConfig payConfig = new WxPayConfig();
        payConfig.setAppId(xcxAccountConfig.getMainAppid());
        payConfig.setMchId(xcxAccountConfig.getMainMchId());
        payConfig.setMchKey(xcxAccountConfig.getMainMchKey());
        payConfig.setNotifyUrl(refundNotify);
        payConfig.setTradeType(PAYMENT_TYPE);
        payConfig.setKeyPath(xcxAccountConfig.getKeyPath());
        if (xcxAccountConfig.getIsSubAccount()) {
            payConfig.setSubAppId(xcxAccountConfig.getSubAppid());
            payConfig.setSubMchId(xcxAccountConfig.getSubMchId());
        }
        wxPayService.setConfig(payConfig);
    }

    /**
     * 保存退款记录信息
     * @param payRefundResult
     */
    private int saveRefundInfo(WxPayRefundResult payRefundResult, XmbWechatPaymentOrder xmbWechatPaymentOrder,WxPayRefundParam refundParam) {
        XmbWechatPaymentRefund wechatPaymentRefund = new XmbWechatPaymentRefund();
        wechatPaymentRefund.setUserId(xmbWechatPaymentOrder.getUserId());
        wechatPaymentRefund.setWxTransactionNo(xmbWechatPaymentOrder.getWxTransactionNo());
        wechatPaymentRefund.setMerchantTransactionNo(xmbWechatPaymentOrder.getMerchantTransactionNo());
        wechatPaymentRefund.setMerchantId(xmbWechatPaymentOrder.getMerchantId());
        wechatPaymentRefund.setMerchantRefundNo(payRefundResult.getOutRefundNo());
        wechatPaymentRefund.setRefundAmount(refundParam.getRefundAmount());
        wechatPaymentRefund.setRefundStatus(PayStatusEnum.refunded.name());
        wechatPaymentRefund.setRefundAmount(refundParam.getRefundAmount());
        wechatPaymentRefund.setTotalAmount(xmbWechatPaymentOrder.getPaymentAmount());
        wechatPaymentRefund.setSenceId(xmbWechatPaymentOrder.getSenceId());
        return wechatPaymentRefundMapper.insertSelective(wechatPaymentRefund);
    }

}
